home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 007 / hashf.cq / hashf.c
Encoding:
Text File  |  1986-03-13  |  12.7 KB  |  569 lines

  1. S 2
  2.  
  3.  
  4. Type P to Pause, S to Stop listing
  5.  
  6. cat puppy.c
  7. # include <stdio.h>
  8.  
  9. long hash();
  10.  
  11. main()
  12. {
  13.     char cmd[16], key[1024], content[1024], fname[100], *bptr;
  14.     int filedesc, mode, size, keysize, contsize, depth;
  15.     long offset;
  16.  
  17.     while (1) {
  18.     printf("? "); 
  19.     gets(cmd);
  20.     switch (cmd[0]) {
  21.     case '?':
  22.         printf("create open klose read write find delete seq hash\n");
  23.         break;
  24.     case 'c':
  25.         printf("Name? "); 
  26.         gets(fname);
  27.         printf("Mode? "); 
  28.         scanf("%d", &mode); 
  29.         getchar();
  30.         printf("Size? "); 
  31.         scanf("%d", &size); 
  32.         getchar();
  33.         filedesc = hcreate(fname, mode, size);
  34.         if (filedesc == -1) printf("Failed\n");
  35.         else printf("Filedesc = %d\n", filedesc);
  36.         break;
  37.     case 'o':
  38.         printf("Name? "); 
  39.         gets(fname);
  40.         printf("Mode? "); 
  41.         scanf("%d", &mode); 
  42.         getchar();
  43.         filedesc = hopen(fname, mode);
  44.         if (filedesc == -1) printf("Failed\n");
  45.         else printf("Filedesc = %d\n", filedesc);
  46.         break;
  47.     case 'k':
  48.         printf("Filedesc? "); 
  49.         scanf("%d", &filedesc); 
  50.         getchar();
  51.         filedesc = hclose(filedesc);
  52.         if (filedesc == -1) printf("Failed\n");
  53.         break;
  54.     case 'r':
  55.         printf("Filedesc? "); 
  56.         scanf("%d", &filedesc); 
  57.         getchar();
  58.         printf("Key? "); 
  59.         gets(key);
  60.         keysize = strlen(key);
  61.         contsize = sizeof(content);
  62.         bptr = content;
  63.         contsize = hread(filedesc, key, keysize, content, contsize);
  64.         if (contsize == -1) printf("Failed");
  65.         else if (contsize > sizeof(content)) printf("Too big");
  66.         else while (contsize--) putchar(*bptr++);
  67.         putchar('\n');
  68.         break;
  69.     case 'w':
  70.         printf("Filedesc? "); 
  71.         scanf("%d", &filedesc); 
  72.         getchar();
  73.         printf("Key? "); 
  74.         gets(key);
  75.         keysize = strlen(key);
  76.         printf("Content? "); 
  77.         gets(content);
  78.         contsize = strlen(content);
  79.         contsize = hwrite(filedesc, key, keysize, content, contsize);
  80.         if (contsize == -1) printf("Failed\n");
  81.         break;
  82.     case 'd':
  83.         printf("Filedesc? "); 
  84.         scanf("%d", &filedesc); 
  85.         getchar();
  86.         printf("Key? "); 
  87.         gets(key);
  88.         keysize = strlen(key);
  89.         contsize = hdelete(filedesc, key, keysize);
  90.         if (contsize == -1) printf("Failed\n");
  91.         break;
  92.     case 'f':
  93.         printf("Filedesc? "); 
  94.         scanf("%d", &filedesc); 
  95.         getchar();
  96.         printf("Key? "); 
  97.         gets(key);
  98.         keysize = strlen(key);
  99.         contsize = hfind(filedesc, key, keysize, &bptr);
  100.         if (contsize == -1) printf("Failed");
  101.         else while (contsize--) putchar(*bptr++);
  102.         putchar('\n');
  103.         break;
  104.     case 's':
  105.         printf("Filedesc? "); 
  106.         scanf("%d", &filedesc); 
  107.         getchar();
  108.         printf("Offset(hex)? "); 
  109.         scanf("%X", &offset); 
  110.         getchar();
  111.         keysize = hseq(filedesc, &bptr, &offset);
  112.         if (keysize == -1) printf("Failed\n");
  113.         else {
  114.         printf("New offset = %x\n", offset);
  115.         while (keysize--) putchar(*bptr++);
  116.         putchar('\n');
  117.         }
  118.         break;
  119.     case 'h':
  120.         printf("Key? "); 
  121.         gets(key);
  122.         printf("Depth? "); 
  123.         scanf("%d", &depth); 
  124.         getchar();
  125.         printf("Hash(hex) = %X\n", hash(key, strlen(key), depth));
  126.         break;
  127.     default:
  128.         printf("Enter ? for help\n");
  129.         break;
  130.     }
  131.     }
  132. }
  133. % cap off
  134. cap: 
  135. Command not found.
  136. Type Selection or M for list, 
  137. P to set protocol, <CR> to exit: 
  138. 1
  139.  
  140.  
  141. Type P to Pause, S to Stop listing
  142.  
  143. cat hashf.c
  144. /*        H A S H F  L I B R A R Y
  145.  
  146.     Accesses data using (key,content) pairs stored in external files.
  147.     Copyright 1985 John Cowan; all rights reserved.
  148.     Permission granted for reproduction in non-commercial uses.
  149.  
  150.     This version has the following data-type dependencies:
  151.     Long must be 4 characters long (32 bits).
  152.     Short must be 2 characters long (16 bits).
  153.     Int may be either.
  154.     Key and buffer sizes are limited by the size of Short.
  155.     File sizes (in bytes) are limited by the size of Long.
  156. */
  157.  
  158. # define FDS 20        /* max number of open files system allows */
  159. static int fd;
  160.  
  161. static struct    {            /* all disk stuff is long for portability */
  162.     long _magic;        /* magic number on disk, open flag in core */
  163.     long _freeblk;        /* pointer to available free block */
  164.     long _bsize;        /* block size of .dat file */
  165.     long _cur;        /* currently resident .dat block, -1 on disk */
  166.     long _len;        /* length of .dat file */
  167.     long _depth;        /* depth of .idx file */
  168.     /* Remaining stuff is meaningless on disk */
  169.     int _idxfd;        /* fd of .idx file */
  170.     char *_block;        /* .dat block buffer */
  171. _header[FDS];
  172.  
  173. # define Header _header[fd]
  174. # define Magic Header._magic
  175. # define Bsize Header._bsize
  176. # define Freeblk Header._freeblk
  177. # define Cur Header._cur
  178. # define Idxfd Header._idxfd
  179. # define Block Header._block
  180. # define Len Header._len
  181. # define Depth Header._depth
  182.  
  183. # define DEFAULT 10        /* default to 1024-byte .dat block size */
  184. # define SETFD \
  185. if (fd = ufd, fd < 0 || fd >= FDS || Magic != DATmagic) \
  186.         return(-1)
  187. # define DATmagic 6460        /* "DAT" in RAD50 */
  188. # define BUFFER(x) (char *)(&x)
  189. # define NONNULL(x) if ((x) == 0) return(-1);
  190.  
  191. # define GETVAL(p) (_t_ = *(p) , _t_+((p)[1]<<8))
  192. # define PUTVAL(p,i) (*(p) = i&0xFF , (p)[1] = i>>8)
  193. static int _t_;
  194.  
  195. # define WALK(b,k,ks,c,cs) \
  196. (ks=GETVAL(b), b+=2, k=b, b+=ks, cs=GETVAL(b), b+=2, c=b, b+=cs)
  197.  
  198. char *strcpy(), *strcat(), *malloc();
  199. long lseek(), hash(), balloc(), getidx();
  200.  
  201. int hcreate(fname, mode, size)
  202. char *fname;
  203. int mode;
  204. int size;
  205. {
  206.     char lname[100];
  207.  
  208.     strcpy(lname, fname);
  209.     if (strlen(fname) > sizeof(lname)) return(-1);
  210.     strcat(lname, ".idx");
  211.     fd = creat(lname, mode);
  212.     if (size == 0) size = DEFAULT;
  213.     if (size < 7) size = 7;
  214.     if (size > 15) return(-1);
  215.     Bsize = 1<<size;
  216.     write(fd, BUFFER(Bsize), 4);
  217.     close(fd);
  218.     strcpy(lname, fname);
  219.     strcat(lname, ".dat");
  220.     fd = creat(lname, mode);
  221.     Magic = DATmagic;
  222.     Freeblk = 0;
  223.     Len = Bsize;
  224.     Depth = 0;
  225.     balloc();        /* also writes out header */
  226.     close(fd);
  227.     Magic = 0;
  228.     return(hopen(fname, 2));
  229. }
  230.  
  231. int hopen(fname, mode)
  232. char *fname;
  233. int mode;
  234. {
  235. # define OPENFAIL {hclose(fd); return(-1);}
  236.     char lname[100];
  237.     extern char *malloc();
  238.  
  239.     if (strlen(fname) > sizeof(lname)) return(-1);
  240.     strcpy(lname, fname);
  241.     strcat(lname, ".dat");
  242.     fd = open(lname, mode);
  243.     read(fd, BUFFER(Header), sizeof(Header));
  244.     if (Magic != DATmagic) OPENFAIL
  245.     strcpy(lname, fname);
  246.     strcat(lname, ".idx");
  247.     Idxfd = open(lname, mode);
  248.     if (Idxfd == -1) OPENFAIL
  249.  
  250.     Cur = -1;
  251.     Block = malloc((unsigned)Bsize);
  252.     if (Block == 0) OPENFAIL
  253.     return(fd);
  254. }
  255.  
  256. hclose(ufd)
  257. int ufd;
  258. {
  259.     SETFD;
  260.     close(fd);
  261.     close(Idxfd);
  262.     if (Block) free(Block);
  263.     Magic = 0;
  264.     return(0);
  265. }
  266.  
  267. int hread(ufd, key, keysize, buff, buffsize)
  268. int ufd;
  269. char *key;
  270. int keysize;
  271. char *buff;
  272. int buffsize;
  273. {
  274.     char *content;
  275.     int contsize;
  276.     register i;
  277.  
  278.     contsize = hfind(ufd, key, keysize, &content);
  279.     if (contsize > 0)
  280.     for (i=0; i < buffsize && i < contsize; i++)
  281.         buff[i] = content[i];
  282.     return (contsize);
  283. }
  284.  
  285. int hfind(ufd, key, keysize, pcontent)
  286. int ufd;
  287. char *key;
  288. int keysize;
  289. char **pcontent;
  290. {
  291.     int contsize;
  292.  
  293.     SETFD; 
  294.     NONNULL(keysize);
  295.     load(getidx(hash(key, keysize, (int)Depth)));
  296.     contsize = search(key, keysize, pcontent);
  297.     return(contsize);
  298. }
  299.  
  300. int hdelete(ufd, key, keysize)
  301. int ufd;
  302. char *key;
  303. int keysize;
  304. {
  305.     char *content;
  306.  
  307.     SETFD; 
  308.     NONNULL(keysize);
  309.     load(getidx(hash(key, keysize, (int)Depth)));
  310.     if (search(key, keysize, &content) == -1) return(-1);
  311.     zap();
  312.     return(rewrite());
  313. }
  314.  
  315. int hwrite(ufd, key, keysize, buff, buffsize)
  316. int ufd;
  317. char *key;
  318. int keysize;
  319. char *buff;
  320. int buffsize;
  321. {
  322.     char *content;
  323.  
  324.     SETFD; 
  325.     NONNULL(keysize); 
  326.     NONNULL(buffsize);
  327.     if (keysize + buffsize + 7 > Bsize) return(-1);
  328.     while (1) {
  329.     load(getidx(hash(key, keysize, (int)Depth)));
  330.     if (search(key, keysize, &content) != -1) zap();
  331.     if (jam(Block, key, keysize, buff, buffsize) != -1) {
  332.         return(rewrite());
  333.     }
  334.     split();
  335.     }
  336. }
  337.  
  338. int hseq(ufd, pkey, poffset)
  339. int ufd;
  340. char **pkey;
  341. long *poffset;
  342. # define Offset *poffset
  343. {
  344.     long himask = ~(Bsize - 1);
  345.     long lomask = Bsize - 1;
  346.     char *blk;
  347.     char *dummy;
  348.     int keysize, dummysize;
  349.  
  350.     SETFD;
  351.     if (Offset == 0) Offset = Bsize;
  352.     blk = Block + (Offset & lomask);
  353.     Offset &= himask;
  354.     if(load(Offset) == -1) return(-1);
  355.     WALK(blk, (*pkey), keysize, dummy, dummysize);
  356.     Offset += GETVAL(blk) ? blk - Block : Bsize;
  357.     return (keysize);
  358. }
  359.  
  360. # define KNUTH 1327217885
  361.  
  362. static unsigned long rotate(i)
  363. unsigned long i;
  364. {
  365.     int bit;
  366.  
  367.     bit = (i & 0x80000000);
  368.     if (bit) i &= 0x7FFFFFFF;
  369.     return((i << 1) + bit);
  370. }
  371.  
  372. long hash(s, len, depth)
  373. char *s;
  374. int len;
  375. int depth;
  376. {
  377.     unsigned long accum = 0;
  378.     long item = 0;
  379.     int shift = 0;
  380.     int i;
  381.  
  382.     for (i=0; i<len; i++) {
  383.     item = (item<<6) + s[i];
  384.     if (++shift == 5) {
  385.         accum = rotate(accum) ^ item;
  386.         item = shift = 0;
  387.     }
  388.     }
  389.     if (shift) accum = rotate(accum) ^ item;
  390.  
  391.     accum *= KNUTH;
  392.     accum = accum >> (32 - depth);
  393.     return (accum);
  394. }
  395.  
  396.  
  397. static load(offset)
  398. long offset;
  399. {
  400.     if (Cur != offset) {
  401.     Cur = offset;
  402.     lseek(fd, Cur, 0);
  403.     if (read(fd, Block, (int)Bsize) == 0) return(-1);
  404.     }
  405.     return(0);
  406. }
  407.  
  408. static int rewrite()
  409. {
  410.     lseek(fd, Cur, 0);
  411.     return((write(fd, Block, (int)Bsize) == -1) ? -1 : 0);
  412. }
  413.  
  414. static long balloc()
  415. {
  416.     long newblk;
  417.     long zero = 0L;
  418.  
  419.     newblk = Len;
  420.     Len += Bsize;
  421.     lseek(fd, Len-4, 0);
  422.     write(fd, BUFFER(zero), 4);
  423.     lseek(fd, newblk, 0);
  424.     write(fd, BUFFER(zero), 4);
  425.     lseek(fd, 0L, 0);
  426.     write(fd, BUFFER(Header), sizeof(Header));
  427.     return(newblk);
  428. }
  429.  
  430. static char *zapmark;
  431.  
  432. static int same(dst, dlen, src, slen)
  433. char *dst, *src;
  434. int dlen, slen;
  435. {
  436.     if (dlen != slen) return(0);
  437.     while (dlen--)
  438.     if (*dst++ != *src++) return(0);
  439.     return(1);
  440. }
  441.  
  442. static int search(key, keysize, pcontent)
  443. char *key;
  444. int keysize;
  445. char **pcontent;
  446. {
  447.     char *blk = Block;
  448.     char *bkey, *cont;
  449.     int bkeysize, contsize;
  450.  
  451.     while (GETVAL(blk)) {
  452.     zapmark = blk;
  453.     WALK(blk, bkey, bkeysize, cont, contsize);
  454.     if (same(key, keysize, bkey, bkeysize)) {
  455.         *pcontent = cont;
  456.         return (contsize);
  457.     }
  458.     }
  459.     return(-1);
  460. }
  461.  
  462. static int zap()
  463. {
  464.     char *zapsrc = zapmark;
  465.     char *key, *cont;
  466.     int size, keysize, contsize;
  467.  
  468.     WALK(zapsrc, key, keysize, cont, contsize);
  469.     while (size = GETVAL(zapsrc)) {
  470.     PUTVAL(zapmark, size);
  471.     zapsrc += 2;
  472.     zapmark += 2;
  473.     while (size--) *zapmark++ = *zapsrc++;
  474.     }
  475.     PUTVAL(zapmark, 0);
  476.     return(GETVAL(Block) == 0);
  477. }
  478.  
  479. static int jam(blk, key, keysize, buff, buffsize)
  480. char *blk, *key, *buff;
  481. int keysize, buffsize;
  482. {
  483.     int size;
  484.     char *blk0;
  485.  
  486.     blk0 = blk;
  487.     while (size = GETVAL(blk)) blk += size + 2;
  488.     if ((blk - blk0) + keysize + buffsize + 7 > Bsize) return(-1);
  489.     /* 2 length words, zero word, r-byte at end of block */
  490.     PUTVAL(blk, keysize);
  491.     blk += 2;
  492.     while (keysize--) *blk++ = *key++;
  493.     PUTVAL(blk, buffsize);
  494.     blk += 2;
  495.     while (buffsize--) *blk++ = *buff++;
  496.     PUTVAL(blk, 0);
  497.     return(0);
  498. }
  499.  
  500. static long getidx(offset)
  501. long offset;
  502. {
  503.     lseek(Idxfd, offset, 0);
  504.     read(Idxfd, BUFFER(offset), 4);
  505.     return(offset);
  506. }
  507.  
  508. # define R Block[Bsize-1]
  509. # define R0 new0[Bsize-1]
  510. # define R1 new1[Bsize-1]
  511.  
  512. static split()
  513. {
  514.     char *new0, *new1;
  515.     long mask, hval, start, finish, i, newblk;
  516.     char *blk = Block;
  517.     int keysize, contsize;
  518.     char *key, *content;
  519.  
  520.     if (R == Depth) expand();
  521.     new0 = malloc((unsigned)Bsize);
  522.     PUTVAL(new0, 0);
  523.     new1 = malloc((unsigned)Bsize);
  524.     PUTVAL(new1, 0);
  525.     mask = 1 << (Depth - ++R);
  526.     while (GETVAL(blk)) {
  527.     WALK(blk, key, keysize, content, contsize);
  528.     hval = hash(key, keysize, (int)Depth);
  529.     if (hval & mask)
  530.         jam(new1, key, keysize, content, contsize);
  531.     else
  532.         jam(new0, key, keysize, content, contsize);
  533.     }
  534.     R0 = R1 = R;
  535.     lseek(fd, Cur, 0);
  536.     write(fd, new0, (int)Bsize);
  537.     newblk = balloc();
  538.     lseek(fd, newblk, 0);
  539.     write(fd, new1, (int)Bsize);
  540.     Cur = -1;
  541.     start = (hval & ~(mask - 1)) | mask;
  542.     finish = start + mask;
  543.     for (i = start; i < finish; i++) {
  544.     lseek(Idxfd, i*4, 0);
  545.     write(Idxfd, BUFFER(newblk), 4);
  546.     }
  547. }
  548.  
  549. static expand()
  550. {
  551.     int idxlen = 1<<Depth;
  552.     long entry[2];
  553.     long register i;
  554.  
  555.     for (i=idxlen-1; i>=0; i--) {
  556.     lseek(Idxfd, i*4, 0);
  557.     read(Idxfd, BUFFER(entry[0]), 4);
  558.     entry[1] = entry[0];
  559.     lseek(Idxfd, i*8, 0);
  560.     write(Idxfd, BUFFER(entry[0]), 8);
  561.     }
  562.     Depth++;
  563. }
  564. Type Selection or M for list, 
  565. P to set protocol, <CR> to exit: 
  566.